package com.wps.netConnection.rpc
{
	import com.wps.netConnection.rpc.event.RpcEvent;

	import flash.events.AsyncErrorEvent;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.NetConnection;
	import flash.net.ObjectEncoding;

	/**
	 * AMF调用服务
	 * @author zhuohongtao
	 */
	public class RemoteService extends RpcService
	{
		private var _serverAddr: String;
		private var _destination: String;

		/**
		 * 构造函数
		 * @param serverAddress 远程过程调用的服务器的地址
		 * @param dest abcd
		 */
		public function RemoteService(serverAddress: String, dest: String)
		{
			super();
			_serverAddr = serverAddress;
			_destination = dest;
		}

		public function destroy(): void
		{
		}

		/**
		 * 服务器地址
		 */
		public function get serverAddr(): String
		{
			return _serverAddr;
		}

		/**
		 *
		 */
		public function get destination(): String
		{
			return _destination;
		}

		/**
		 * 调用远程方法
		 * @param method 方法名
		 * @param args 方法参数
		 * @return rpcToken，调用的唯一标识，并记录调用信息
		 */
		public function call(method: String, args: Object): RpcToken
		{
			return callBy(method, _serverAddr, args);
		}

		/**
		 * 调用不同于默认地址的远程方法
		 * @param method 方法名
		 * @param server 服务器地址
		 * @param args 方法参数
		 * @return rpcToken，调用的唯一标识，并记录调用信息
		 */
		public function callBy(method: String, server: String, args: Object): RpcToken
		{
			var connection: NetConnectionProxy = _getConnection(server);
			connection.call(_destination + "." + method, args);

			var token: RpcToken = new RpcToken(_tokenIndex ++, method, args, connection);
			_tokens.addToken(token);
			return token;
		}

		/**
		 * 停止一个正在进行的调用
		 * @param token 调用的唯一标识
		 * @return
		 */
		public function close(token: RpcToken): Boolean
		{
			NetConnection(token.connection.connection).close();
			_tokens.removeToken(token);
			return true;
		}

		/**
		 * 生成一个NetConnection对象的代理, 并添加它的一些错误事件监听器,把错误派发到外部处理.
		 * @private
		 * @return
		 */
		private function _getConnection(server: String): NetConnectionProxy
		{
			var connection: NetConnection = new NetConnection();
			connection.objectEncoding = ObjectEncoding.AMF3;
			connection.connect(server);
			connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, _asyncErrorHandler);
			connection.addEventListener(IOErrorEvent.IO_ERROR, _ioErrorHandler);
			connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _securityErrorHandler);
			connection.addEventListener(NetStatusEvent.NET_STATUS, _netStatusHandler);
			return new NetConnectionProxy(connection, _resultHandler, _faultHandler);
		}

		/**
		 * 网络同步错误事件再发派到外部处理
		 * @private
		 */
		private function _asyncErrorHandler(event: AsyncErrorEvent): void
		{
			_dispatchRpcEvent(event.target as NetConnection, RpcEvent.StatusCodeAsyncError, event.error.message);
		}

		/**
		 * IO错误事件再发派到外部处理
		 * @private
		 */
		private function _ioErrorHandler(event: IOErrorEvent): void
		{
			_dispatchRpcEvent(event.target as NetConnection, RpcEvent.StatusCodeIOError, event.text);
		}

		/**
		 * 安全错误事件再发派到外部处理
		 * @private
		 */
		private function _securityErrorHandler(event: SecurityErrorEvent): void
		{
			_dispatchRpcEvent(event.target as NetConnection, RpcEvent.StatusCodeSecurityError, event.text);
		}

		/**
		 * 请求成功事件再派发到外部处理
		 * @private
		 */
		private function _resultHandler(connection: NetConnection, info: Object): void
		{
			_dispatchRpcEvent(connection, RpcEvent.StatusCodeSucceed, info);
		}

		/**
		 * 请求失败事件再派发到外部处理
		 * @private
		 */
		private function _faultHandler(connection: NetConnection, info: Object): void
		{
			_dispatchRpcEvent(connection, RpcEvent.StatusCodeRequestFault, info);
		}

		/**
		 * 网络状态事件再派发到外部处理
		 * @private
		 */
		private function _netStatusHandler(event: NetStatusEvent): void
		{
			if (event.info["level"] == "error")
			{
				_dispatchRpcEvent(event.target as NetConnection, RpcEvent.StatusCodeStatusError, event.info);
			}
//			var str: String = "netStatus";
//			for (var key: * in event.info)
//				str += ", " + key.toString() + ": \"" + event.info[key].toString() + "\"";
//			trace(str + ".");
		}

		/**
		 * 派发rpc事件
		 * @param connection 发出连接的NetConnection
		 * @param code 返回代码
		 * @param info 返回信息
		 */
		private function _dispatchRpcEvent(connection: NetConnection, code: int, info: Object): void
		{
			var index: int = _tokens.getTokenIndexByConnection(connection);
			if (index != -1)
			{
				var token: RpcToken = _tokens.getToken(index);
				_tokens.removeAt(index);
				connection.close();
				dispatchEvent(new RpcEvent(token, code, info));
			}
			else
			{
				trace("wrong");
			}
		}
	}
}

import flash.net.NetConnection;
import flash.net.Responder;

/**
 * NetConnection代理，用于在回调函数中记录NetConnection对象。
 * @author zhuohongtao
 */
class NetConnectionProxy
{
	private var _connection: NetConnection;
	private var _result: Function;
	private var _status: Function;

	public function NetConnectionProxy(connection: NetConnection, result: Function, status: Function = null)
	{
		_connection = connection;
		_result = result;
		_status = status;
	}

	public function get connection(): NetConnection
	{
		return _connection;
	}

	public function call(command: String, arguments: Object): void
	{
		var responder: Responder = new Responder(_resultHander, _faultHandler);
		_connection.call(command, responder, arguments);
	}

	private function _resultHander(info: Object): void
	{
		_result(_connection, info);
	}

	private function _faultHandler(info: Object): void
	{
		_status(_connection, info);
	}
}
